package top.ffhome.system.service.impl;

import java.util.List;
import java.util.Set;

import org.apache.shiro.crypto.SecureRandomNumberGenerator;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import cn.hutool.core.collection.CollUtil;
import top.ffhome.common.audit.AuditOperation;
import top.ffhome.common.audit.AuditService;
import top.ffhome.common.page.PageRequest;
import top.ffhome.common.page.PageResult;
import top.ffhome.common.service.impl.BaseServiceImpl;
import top.ffhome.system.constant.SysConstants;
import top.ffhome.system.entity.SysMenu;
import top.ffhome.system.entity.SysUser;
import top.ffhome.system.mapper.SysUserMapper;
import top.ffhome.system.service.SysUserService;
import top.ffhome.util.bean.BeanUtil;
import top.ffhome.util.core.StrUtil;
import top.ffhome.util.core.TreeUtil;

@Service
@AuditService(entity = SysUser.class)
public class SysUserServiceImpl extends BaseServiceImpl<SysUser, SysUserMapper> implements SysUserService {
	@Override
	@CacheEvict(value = { "user_selectByAccount", "user_selectPermsByAccount" }, allEntries = true)
	public void clearCache() {
	}

	@Override
	protected void beforeSave(SysUser entity) {
		if (StrUtil.isNotBlank(entity.getPassword())) {
			// 生成盐,默认长度 16 位
			String salt = new SecureRandomNumberGenerator().nextBytes().toString();
			entity.setSalt(salt);
			entity.setPassword(encrypt(entity.getPassword(), salt));
		} else {
			entity.setSalt(null);
		}
		super.beforeSave(entity);
	}

	@Override
	protected void afterSave(SysUser entity) {
		saveRoleRelation(entity);
		super.afterSave(entity);
	}

	@Override
	protected void afterDelete(List<Long> ids) {
		for (Long id : ids) {
			mapper.deleteRoleRelation(id);
		}
		super.afterDelete(ids);
	}

	/**
	 * 保存人员与角色关联处理
	 * 
	 * @param entity
	 */
	private void saveRoleRelation(SysUser entity) {
		if (entity.getRoleIds() == null || entity.getRoleIds().size() == 0) {
			return;
		}
		mapper.deleteRoleRelation(entity.getId());
		mapper.insertRoleRelation(entity.getId(), entity.getRoleIds());
	}

	@Override
	public String encrypt(String password, String salt) {
		return new SimpleHash("md5", password, salt, 2).toString();
	}

	@Override
	@Cacheable(value = "user_selectByAccount", unless = "#result == null")
	public SysUser selectByAccount(String account) {
		SysUser dto = new SysUser();
		dto.setAccount(account);
		dto.setStatus(SysConstants.NORMAL);
		List<SysUser> list = mapper.select(dto);
		if (list.size() == 1) {
			return list.get(0);
		}
		return null;
	}

	@Override
	public Set<Long> selectRoleIdsByUserId(Long userId) {
		SysUser dto = new SysUser();
		dto.setId(userId);
		// 此处使用了id别名替代了角色的ID，只在此内部处理，只是为减少一个字段的定义
		dto.getParams().put("fields", "ur.role_id id");
		dto.getParams().put("joinUserRole", "Y");
		List<SysUser> list = mapper.select(dto);
		Set<Long> sets = CollUtil.newHashSet();
		for (SysUser u : list) {
			sets.add(u.getId());
		}
		return sets;
	}

	@Override
	public List<SysMenu> selectRoutersByUserId(Long userId) {
		return mapper.selectRoutersByUserId(userId);
	}

	@Override
	public List<SysMenu> selectMenusByUserId(Long userId) {
		List<SysMenu> list = mapper.selectMenusByUserId(userId);
		return TreeUtil.generate(list, new SysMenu());
	}

	@Override
	@Cacheable(value = "user_selectPermsByAccount", unless = "#result == null || #result.size() == 0")
	public Set<String> selectPermsByAccount(String account) {
		SysUser user = selectByAccount(account);
		return selectPermsByUserId(user.getId());
	}

	@Override
	public Set<String> selectPermsByUserId(Long userId) {
		return mapper.selectPermsByUserId(userId);
	}

	@Override
	@AuditOperation(type = AuditOperation.UPDATE)
	public int resetPassword(SysUser user) {
		SysUser u = new SysUser();
		BeanUtil.copyProperties(user, u, CollUtil.newArrayList("id", "password", "salt"));
		return mapper.update(u);
	}

	@Override
	public boolean checkAccountUnique(String account) {
		return selectByAccount(account) == null;
	}

	@Override
	public PageResult<SysUser> select(PageRequest request) {
		StringBuffer sb = new StringBuffer();
		sb.append("u.id,u.account,u.name,u.status,u.update_time,updateBy.name update_by_name");
		sb.append(",(select group_concat(r.name) from sys_role r, sys_user_role ur");
		sb.append(" where r.id=ur.role_id and ur.user_id=u.id group by ur.user_id order by r.sort) roles");
		request.getParams().put("fields", sb.toString());
		if (StrUtil.isNotBlank(request.getParams().get("role"))) {
			request.getParams().put("joinUserRole", "Y");
		}
		return super.select(request);
	}
}
